package EncryptionAndSecurity.数字证书;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.X509Certificate;

/**
 * @Description:
 * @Author: Administrator
 * @Date: 2020-04-19
 */
public class Main {
    public static void main(String[] args) throws Exception {
        byte[] message =
                "Hello,user X.509 cert!".getBytes("utf-8");

        //读取KeyStore
        KeyStore ks = loadKeyStore("my.keystore", "123456");
        //读取私钥
        PrivateKey privateKey = (PrivateKey) ks.getKey("mycert", "123456".toCharArray());
        //读取证书
        X509Certificate certificate = (X509Certificate) ks.getCertificate("mycert");

        //加密
        byte[] encrypted = encrypt(certificate, message);

        System.out.println(String.format("encrypted: %x", new BigInteger(1, encrypted)));

        //解密
        byte[] decrypted = decrypt(privateKey, encrypted);

        System.out.println(String.format("decrypted: %x", new BigInteger(1, decrypted)));
        //签名
        byte[] sign = sign(privateKey, certificate, message);

        System.out.println(String.format("signed: %x", new BigInteger(1, sign)));

        //验证签名
        boolean verified = verify(certificate, message, sign);
        System.out.println("verify:" + verified);
    }

    private static boolean verify(X509Certificate certificate, byte[] message, byte[] sign) throws
            Exception {
        Signature signature = Signature.getInstance(certificate.getSigAlgName());
        signature.initVerify(certificate);
        signature.update(message);
        return signature.verify(sign);
    }

    private static byte[] sign(PrivateKey privateKey, X509Certificate certificate, byte[] message)
            throws Exception{
        Signature signature = Signature.getInstance(certificate.getSigAlgName());
        signature.initSign(privateKey);
        signature.update(message);
        return signature.sign();
    }

    private static byte[] decrypt(PrivateKey privateKey, byte[] data) throws Exception{
        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(data);

    }

    private static byte[] encrypt(X509Certificate certificate, byte[] message) throws Exception {
        Cipher cipher = Cipher.getInstance(certificate.getPublicKey().getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey());

        return cipher.doFinal(message);
    }

    private static KeyStore loadKeyStore(String keyStoreFile, String password) {
        try {
            InputStream input = Main.class.getResourceAsStream(keyStoreFile);
            if (input == null) {
                throw new RuntimeException("file not fouond int classpath: " + keyStoreFile);
            }
            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
            ks.load(input, password.toCharArray());
            return ks;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }
}
